package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.login.GuiGuLogin;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcloud.vod.VodUploadClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@Slf4j
@Service
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @GuiGuLogin
    @Override
    public void saveTrackInfo(TrackInfoVo trackInfoVo) {
        TrackInfo trackInfo = new TrackInfo();
        BeanUtils.copyProperties(trackInfoVo,trackInfo);


        //声音表
        //根据文件id查询媒体信息
        TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        if (mediaInfo==null){
            return;
        }
        Float duration = mediaInfo.getDuration();
        Long size = mediaInfo.getSize();
        String type = mediaInfo.getType();
        String mediakUrl = mediaInfo.getMediakUrl();
        trackInfo.setMediaDuration(new BigDecimal(duration));
        trackInfo.setMediaSize(size);
        trackInfo.setMediaType(type);
        trackInfo.setMediaUrl(mediakUrl);


        //设置用户的ID 从authcontext
        Long userId = AuthContextHolder.getUserId()==null?1:AuthContextHolder.getUserId();
        trackInfo.setUserId(userId);

        //查询同一个专辑下最大的声音序号 +1
        TrackInfo temp = trackInfoMapper.selectOne(new LambdaQueryWrapper<TrackInfo>()
                .eq(TrackInfo::getAlbumId, trackInfoVo.getAlbumId())
                .orderByDesc(TrackInfo::getOrderNum)
                .last("limit 1")
                .select(TrackInfo::getOrderNum));
        trackInfo.setOrderNum(temp==null?1: temp.getOrderNum()+1);

        //来源
        trackInfo.setSource(SystemConstant.TRACK_SOURCE_USER);
        //审核状态
        trackInfo.setStatus(SystemConstant.TRACK_STATUS_NO_PASS);
        //初始化 track_stat 表
        this.save(trackInfo);
        Long id = trackInfo.getId();

        //声音统计表
        initTrackStat(id,SystemConstant.TRACK_STAT_PLAY);
        initTrackStat(id,SystemConstant.TRACK_STAT_COLLECT);
        initTrackStat(id,SystemConstant.TRACK_STAT_PRAISE);
        initTrackStat(id,SystemConstant.TRACK_STAT_COMMENT);
        //include_track_count
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
        Integer includeTrackCount = albumInfo.getIncludeTrackCount();
        albumInfo.setIncludeTrackCount(includeTrackCount+1);
        albumInfoMapper.updateById(albumInfo);
    }

    @GuiGuLogin
    @Override
    public Page<TrackListVo> findUserTrackPage(Page<TrackListVo> page1, TrackInfoQuery trackInfoQuery) {
        //根据用户id查询 所有声音信息 info stat
        Long userId = AuthContextHolder.getUserId();
        trackInfoQuery.setUserId(userId==null?1:userId);
        return this.trackInfoMapper.findUserTrackPage(page1,trackInfoQuery);


    }
    @GuiGuLogin
    @Override
    public void updateTrackInfo(Long trackId, TrackInfoVo trackInfoVo) {

        TrackInfo trackInfo = this.getById(trackId);

        if (ObjectUtils.isEmpty(trackInfo)){
            return;
        }

        //设置用户Id
        Long userId =AuthContextHolder.getUserId()==null?1:AuthContextHolder.getUserId();
        trackInfo.setUserId(userId);
        TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
        //判断前端传的

        if (!trackInfo.getMediaFileId().equals(trackInfoVo.getMediaFileId())){
            if (mediaInfo!=null){
                Float duration = mediaInfo.getDuration();
                String type = mediaInfo.getType();
                Long size = mediaInfo.getSize();
                String mediakUrl = mediaInfo.getMediakUrl();
                trackInfo.setMediaDuration(new BigDecimal(duration));
                trackInfo.setMediaType(type);
                trackInfo.setMediaSize(size);
                trackInfo.setMediaUrl(mediakUrl);

            }

        }
        BeanUtils.copyProperties(trackInfoVo,trackInfo);
        this.updateById(trackInfo);


    }

    @Override
    public void removeTrackInfo(Long trackId) {
        //删除统计表
        this.trackStatMapper.delete(new LambdaUpdateWrapper<TrackStat>().eq(TrackStat::getTrackId,trackId));

        TrackInfo trackInfo = this.trackInfoMapper.selectOne(new LambdaQueryWrapper<TrackInfo>().eq(TrackInfo::getId, trackId));
        Long albumId = trackInfo.getAlbumId();

        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()-1);


        //删除主表
        this.trackStatMapper.delete(new LambdaUpdateWrapper<TrackStat>().eq(TrackStat::getTrackId,trackInfo.getId()));

        //删除音频信息 第三方
        vodService.removeMediaInfo(trackInfo.getMediaFileId());

    }

    @Override
    public Page<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> pageL, Long albumId) {
        //根据专辑id查询专辑
        AlbumInfo albumInfo = this.albumInfoMapper.selectById(albumId);
        if (albumInfo ==null){
            throw  new GuiguException(ResultCodeEnum.ILLEGAL_REQUEST);
        }
        //根据专辑id查询出所有的声音信息
        Page<AlbumTrackListVo> albumTrackListVoPage =  this.trackInfoMapper.findUserTrackPages(pageL,albumId);
        if (albumTrackListVoPage==null || CollectionUtils.isEmpty(albumTrackListVoPage.getRecords())){
            return null;
        }
        //先判断付费类型       过滤免费的专辑声音
        List<AlbumTrackListVo> albumTrackListVos = albumTrackListVoPage.getRecords();
        //如果是免费的专辑 直接返回
        if (StringUtils.equals(albumInfo.getPayType(),SystemConstant.ALBUM_PAY_TYPE_FREE)){
            return albumTrackListVoPage;
        }
        //获取当前页 需要付费的声音列表，过滤掉免费试听的
        List<AlbumTrackListVo> needPaidTracks = albumTrackListVos.stream().filter(albumTrackListVo ->
                albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(needPaidTracks)){
            return albumTrackListVoPage;
        }

        //获取登录状态
        Long userId = AuthContextHolder.getUserId();

        //如果没登录 则该付费显示付费
        if (userId==null){
            needPaidTracks.forEach(needPaidTrack->{
                needPaidTrack.setIsShowPaidMark(true);
            });
            return albumTrackListVoPage;
        }

        //获取用户信息
        Result<UserInfo> userInfoById = this.userInfoFeignClient.getUserInfoById(userId);
        Assert.notNull(userInfoById,"声音分页查询,获取用户信息失败");
        UserInfo userInfo = userInfoById.getData();
        if (userInfo==null){
            throw new RuntimeException("用户信息异常");
        }

        //判断用户是否为vip
        if (userInfo.getIsVip()==1 && userInfo.getVipExpireTime().after(new Date()) && albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_VIPFREE)){
            return albumTrackListVoPage;
        }


        //查询当前用户是否购买过专辑
        Result<Boolean> paidAlbum = this.userInfoFeignClient.isPaidAlbum(albumId);
        Assert.notNull(paidAlbum,"根据专辑查询声音分页查询失败,调用是否购买专辑失败");
        Boolean isPaidAlbum = paidAlbum.getData();
        //已经买过了直接返回即可
        if (isPaidAlbum!=null && isPaidAlbum){
            return albumTrackListVoPage;
        }

        //查询该专辑下已经购买过声音
        Result<List<UserPaidTrack>> paidTracks = this.userInfoFeignClient.getPaidTracks(albumId);
        Assert.notNull(paidTracks,"根据专辑查询声音分页查询失败，调用是否购买声音失败");
        List<UserPaidTrack> userPaidTracks = paidTracks.getData();

        //如果一个声音都没买
        if (CollectionUtils.isEmpty(userPaidTracks)){
            needPaidTracks.forEach( track->{
                        track.setIsShowPaidMark(true);});
            return albumTrackListVoPage;
        }
        //如果有买过的声音
        List<Long> userPaidedId = userPaidTracks.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
        needPaidTracks.forEach(track->{
            if (!userPaidedId.contains(track.getTrackId())){
                track.setIsShowPaidMark(true);
            }
        });



        return albumTrackListVoPage;
    }

    @Override
    public TrackStatVo getTrackStatVo(Long trackId) {
        return this.trackInfoMapper.getTrackStatVo(trackId);
    }

    private void initTrackStat(Long id,String type) {
        TrackStat trackStat = new TrackStat();
        trackStat.setTrackId(id);
        trackStat.setStatType(type);
        this.trackStatMapper.insert(trackStat);
    }
}
